import {
  computed,
  defineComponent,
  onMounted,
  ref,
  PropType,
  watch,
} from "vue";
import { Namespace } from "@qx-chitanda/scss-utils";
import { editor } from "monaco-editor";
import * as monaco from "monaco-editor";
import { merge } from "lodash-es";
import { monacoEnvironment } from "./dependencies";
import "./monaco-editor.scss";

const CUSTOM_LANGUAGE = "custom_";

(window as any).MonacoEnvironment = monacoEnvironment;

export const MonacoEditor = defineComponent({
  name: "MonacoEditor",
  props: {
    value: {
      type: String,
    },
    options: {
      type: Object as PropType<editor.IStandaloneEditorConstructionOptions>,
    },
  },
  emits: ["update:value"],
  setup(props, { emit }) {
    const ns = new Namespace("monaco-editor", "qx");

    // 正则匹配零宽字符包围内字符
    // const reg = /​([^​]*)​/;

    const containerRef = ref<HTMLDivElement>();

    let editorInst: editor.IStandaloneCodeEditor | null = null;

    const inst = computed<editor.IStandaloneCodeEditor>(() => editorInst!);

    watch(
      () => props.value,
      (val) => {
        inst.value.setValue(val || "");
      }
    );

    const val = computed({
      get() {
        return props.value ?? "";
      },
      set(val) {
        emit("update:value", val);
      },
    });

    let option: editor.IStandaloneEditorConstructionOptions = {
      value: val.value ?? "", // 编辑器内容
      language: CUSTOM_LANGUAGE,
      automaticLayout: true, // 是否自动布局
      theme: `CustomTheme`,
      readOnly: false,
      wordWrap: "on", // 当单行文本太长时截断换行，true 为换行，false 为不换行
      scrollBeyondLastLine: false, // 滚动完最后一行后再滚动一屏幕
      // 是否开启小地图
      minimap: {
        enabled: true,
      },
      tabSize: 2, // tab缩进长度
      autoClosingBrackets: "beforeWhitespace", // 是否自动添加结束括号(包括中括号) "always" | "languageDefined" | "beforeWhitespace" | "never"
      autoClosingDelete: "auto", // 是否自动删除结束括号(包括中括号) "always" | "never" | "auto"
      autoClosingOvertype: "auto", // 是否关闭改写 即使用insert模式时是覆盖后面的文字还是不覆盖后面的文字 "always" | "never" | "auto"
      autoClosingQuotes: "beforeWhitespace", // 是否自动添加结束的单引号 双引号 "always" | "languageDefined" | "beforeWhitespace" | "never"
      comments: {
        ignoreEmptyLines: true, // 插入行注释时忽略空行。默认为真。
        insertSpace: true, // 在行注释标记之后和块注释标记内插入一个空格。默认为真。
      }, // 注释配置
      columnSelection: false, // 启用列编辑 按下shift键位然后按↑↓键位可以实现列选择 然后实现列编辑
      folding: true, // 是否启用代码折叠
      fixedOverflowWidgets: true, // 超出编辑器大小的使用fixed属性显示
      // 编辑器悬停配置
      hover: {
        sticky: true, // 悬停是否粘滞，可以点击并选择其内容
        above: false, // 悬停是否应该显示在直线上方
      },
    };

    if (props.options) {
      option = merge(option, props.options);
    }

    function initEditor(): void {
      monaco.languages.register({ id: CUSTOM_LANGUAGE });
      monaco.languages.setMonarchTokensProvider(CUSTOM_LANGUAGE, {
        keywords: ["IF", "AND"],
        tokenizer: {
          root: [
            // 标识符
            [
              /[a-zA-Z_]\w*/,
              {
                cases: {
                  "@keywords": "keyword",
                  "@default": "variable",
                },
              },
            ],
            // 字段变量
            [/​([^​]*)​/, "variable"],
          ],
          comment: [
            [/.*/, "comment", "@pop"], // 单行注释
          ],
        },
      });
      monaco.editor.defineTheme("CustomTheme", {
        base: "vs",
        inherit: false,
        rules: [
          { token: "keyword", foreground: "#ff0000" },
          { token: "identifier", foreground: "#ff0022", fontStyle: "bold" },
          { token: "variable", foreground: "#ffa500", background: "#616161" },
        ],
        colors: {
          "editor.foreground": "#000000",
        },
      });
      monaco.languages.setLanguageConfiguration(CUSTOM_LANGUAGE, {
        autoClosingPairs: [
          {
            open: "(",
            close: ")",
          },
          {
            open: "[",
            close: "]",
          },
          {
            open: '"',
            close: '"',
          },
          {
            open: "'",
            close: "'",
          },
        ],
      });
      monaco.languages.registerHoverProvider(CUSTOM_LANGUAGE, {
        provideHover: (model, position) => {
          const word = model.getWordAtPosition(position);
          if (word) {
            return {
              range: new monaco.Range(
                position.lineNumber,
                word.startColumn,
                position.lineNumber,
                word.endColumn
              ),
              contents: [
                {
                  value: `## 标题`,
                },
                {
                  value: `| 左对齐 | 居中对齐 | 右对齐 |
| :--------- | :-------: | ----------: |
| 单元格 | 单元格 | 单元格 |
| 单元格 | 单元格 | 单元格 |`,
                },
              ],
            };
          }
        },
      });
      monaco.languages.registerCompletionItemProvider(CUSTOM_LANGUAGE, {
        triggerCharacters: ['>'],
        provideCompletionItems: function (model, position) {
          const word = model.getWordUntilPosition(position);
          const range = new monaco.Range(
            position.lineNumber,
            word.startColumn,
            position.lineNumber,
            word.endColumn
          );
          return {
            suggestions: [
              {
                label: ">=",
                kind: monaco.languages.CompletionItemKind.Unit,
                insertText: ">=",
                range,
                documentation: "测试内容",
              },
              {
                label: ">>",
                kind: monaco.languages.CompletionItemKind.Unit,
                insertText: ">>",
                range,
                documentation: "测试内容2",
              },
            ],
          };
        },
      });

      editorInst = monaco.editor.create(containerRef.value!, option);
      const _ = inst.value;
      _.onDidChangeModelContent(() => {
        val.value = _.getValue();
      });
      _.updateOptions({
        unicodeHighlight: {
          invisibleCharacters: false, // 隐藏零宽字符特殊显示
        },
      });
    }

    onMounted(() => {
      initEditor();
      defaultCode();
    });

    function defaultCode(): void {
      if (inst.value) {
        const _ = inst.value;
        _.setValue(
          `IF(AND(​表单form_101157884.ID​ ​表单form_101157884.租户ID​), ​表单form_101157884.创建时间​ + ​表单form_101157884.修改时间​, ​表单form_101157884.创建人​ + (​表单form_101157884.修改人​ + ​表单form_101157884.修改人​))`
        );

        const t = _.getModel()!;

        const match = t.findMatches("​([^​]*)​", true, true, false, null, true);

        const decorations: editor.IModelDeltaDecoration[] = [];

        match.forEach((item) => {
          decorations.push({
            range: item.range,
            options: {
              inlineClassName: "test-inline-decoration",
            },
          });
        });

        _.createDecorationsCollection(decorations);

        const model = _.getModel()!;

        monaco.editor.setModelMarkers(model, "*", [
          {
            startLineNumber: 2,
            startColumn: 1,
            endLineNumber: 2,
            endColumn: 9,
            message: '不能使用 function',
            severity: monaco.MarkerSeverity.Error,
          },
        ]);
      }
    }

    return { ns, containerRef };
  },
  render() {
    return (
      <div class={this.ns.b()}>
        <div ref="containerRef" class={this.ns.e("editor")}></div>
      </div>
    );
  },
});
